#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>

#define PORT 8080
#define BUFFER_SIZE 1024
#define MAX_REQUEST_SIZE 4096
#define DOCUMENT_ROOT "./www"  // 静态文件根目录

// 发送 HTTP 响应头
void send_response_header(int client_socket, int status_code, const char *content_type) {
    const char *status_line;
    if (status_code == 200) {
        status_line = "HTTP/1.1 200 OK\r\n";
    } else if (status_code == 404) {
        status_line = "HTTP/1.1 404 Not Found\r\n";
    } else if (status_code == 500) {
        status_line = "HTTP/1.1 500 Internal Server Error\r\n";
    } else {
        status_line = "HTTP/1.1 400 Bad Request\r\n";
    }
    
    char response_header[BUFFER_SIZE];
    sprintf(response_header, "%s"
                     "Content-Type: %s\r\n"
                     "Connection: close\r\n"
                     "\r\n",
            status_line, content_type);
    
    send(client_socket, response_header, strlen(response_header), 0);
}

// 处理客户端请求
void handle_client(int client_socket) {
    char request[MAX_REQUEST_SIZE] = {0};
    int bytes_received = recv(client_socket, request, MAX_REQUEST_SIZE - 1, 0);
    if (bytes_received <= 0) {
        close(client_socket);
        return;
    }
    
    // 解析请求行 (例如: "GET /index.html HTTP/1.1")
    char method[BUFFER_SIZE], path[BUFFER_SIZE], version[BUFFER_SIZE];
    sscanf(request, "%s %s %s", method, path, version);
    
    // 仅处理 GET 请求
    if (strcmp(method, "GET") != 0) {
        send_response_header(client_socket, 400, "text/html");
        const char *error_page = "<h1>400 Bad Request</h1><p>Only GET method is supported.</p>";
        send(client_socket, error_page, strlen(error_page), 0);
        close(client_socket);
        return;
    }
    
    // 构建文件路径
    char file_path[BUFFER_SIZE];
    if (strcmp(path, "/") == 0) {
        strcpy(file_path, DOCUMENT_ROOT);
        strcat(file_path, "/index.html");
    } else {
        strcpy(file_path, DOCUMENT_ROOT);
        strcat(file_path, path);
    }
    
    // 检查文件是否存在
    struct stat file_stat;
    if (stat(file_path, &file_stat) < 0) {
        send_response_header(client_socket, 404, "text/html");
        const char *error_page = "<h1>404 Not Found</h1><p>The requested resource was not found.</p>";
        send(client_socket, error_page, strlen(error_page), 0);
        close(client_socket);
        return;
    }
    
    // 确定内容类型
    const char *content_type = "text/html";
    if (strstr(file_path, ".css")) content_type = "text/css";
    else if (strstr(file_path, ".js")) content_type = "application/javascript";
    else if (strstr(file_path, ".jpg") || strstr(file_path, ".jpeg")) content_type = "image/jpeg";
    else if (strstr(file_path, ".png")) content_type = "image/png";
    else if (strstr(file_path, ".gif")) content_type = "image/gif";
    
    // 发送响应头
    send_response_header(client_socket, 200, content_type);
    
    // 发送文件内容
    int file_fd = open(file_path, O_RDONLY);
    if (file_fd < 0) {
        send_response_header(client_socket, 500, "text/html");
        const char *error_page = "<h1>500 Internal Server Error</h1><p>Failed to open file.</p>";
        send(client_socket, error_page, strlen(error_page), 0);
        close(client_socket);
        return;
    }
    
    char buffer[BUFFER_SIZE];
    int bytes_read;
    while ((bytes_read = read(file_fd, buffer, BUFFER_SIZE)) > 0) {
        send(client_socket, buffer, bytes_read, 0);
    }
    
    close(file_fd);
    close(client_socket);
}

int main() {
    // 创建套接字
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (server_socket < 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }
    
    // 设置套接字选项，允许地址重用
    int opt = 1;
    if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
        perror("Setsockopt failed");
        exit(EXIT_FAILURE);
    }
    
    // 准备服务器地址
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);
    
    // 绑定套接字
    if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("Bind failed");
        exit(EXIT_FAILURE);
    }
    
    // 监听连接
    if (listen(server_socket, 5) < 0) {
        perror("Listen failed");
        exit(EXIT_FAILURE);
    }
    
    printf("Server listening on port %d...\n", PORT);
    printf("Document root: %s\n", DOCUMENT_ROOT);
    
    // 接受客户端连接
    while (1) {
        struct sockaddr_in client_addr;
        socklen_t client_addr_len = sizeof(client_addr);
        int client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_addr_len);
        
        if (client_socket < 0) {
            perror("Accept failed");
            continue;
        }
        
        printf("New connection from %s:%d\n", 
               inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
        
        // 处理客户端请求
        handle_client(client_socket);
    }
    
    // 关闭服务器套接字
    close(server_socket);
    return 0;
}